package question.interview;

import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.Comparator.comparingLong;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

/**
 * List去重
 * 参考 https://blog.csdn.net/jiaobuchong/article/details/54412094
 */
public class ListDeduplication {
    static List<String> stringList = new ArrayList<>();
    static List<Person> persons = new ArrayList<>();
    static {
        stringList.add("aa");
        stringList.add("bb");
        stringList.add("aa");
        stringList.add("bb");
        persons.add( new Person(1l, "jack"));
        persons.add( new Person(1l, "jack"));
        persons.add( new Person(1l, "jacks"));
        persons.add( new Person(3l, "jack chou"));
        persons.add( new Person(2l, "tom"));
        persons.add( new Person(4l, "hanson"));
        persons.add( new Person(5l, "胶布虫"));
    }
    /**
     * 通过HashSet去重,此时的Hash值就是字符串直接hash，如果是对象的话需要重写Hash方法
     */
    @Test
    public void removeStringListDupli() {

        Set<String> set = new LinkedHashSet<>();
        set.addAll(stringList);
        stringList.clear();
        stringList.addAll(set);
        System.out.println("去重后字符串");
        System.out.println(stringList);
    }

    /**
     * Java8的Lambda表达式
     */
    @Test
    public void removeStringListDupli4Java8() {
        List<String> collect = stringList.stream().distinct().collect(Collectors.toList());
        System.out.println(collect);
    }


    /**
     * 不重写 hashCode 时，此时不会没有去重，不会根据Id或者name进行去重，因为此时的hash是整个对象，而不是id和name的值。
     * 重写了 hashCode不重写equals ，此时hashcode的值一样，但是两个对象之间的判断是==，判断是否是同一个对象，此时也会导致去重失败。
     * 所以需要重写hashcode先判断两个对象的hash值是否一样，然后再判断两个对象内容是否一样。
     */
    @Test
    public void removePersonListDupli() {

        Set<Person> set = new LinkedHashSet<>();
        set.addAll(persons);
        persons.clear();
        persons.addAll(set);
        System.out.println("去重后Person对象");
        System.out.println(persons);
    }

    /**
     * 根据id去重，无需重写hashcode和equals方法
     */
    @Test
    public void  removeDupliById() {
        Set<Person> personSet = new TreeSet<>((o1, o2) -> o1.getId().compareTo(o2.getId()));
        personSet.addAll(persons);
        System.out.println(personSet);
    }
    /**
     * 根据id去重，无需重写hashcode和equals方法,使用lambda表达式
     * 有点复杂没看懂？
     */
    @Test
    public void  removeDupliById4Lambda() {
        ArrayList<Person> collect = persons.stream().collect(
                collectingAndThen(
                        toCollection(() -> new TreeSet<>(comparingLong(Person::getId))), ArrayList::new)
        );
        System.out.println(collect);
    }
}

class Person {
    private Long id;

    private String name;

    public Person(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }


//    @Override
//    public boolean equals(Object o) {
////        return super.equals(o);
//        if (this == o) return true;
//        if (o == null || getClass() != o.getClass()) return false;
//
//        Person person = (Person) o;
//
//        if (!id.equals(person.id)) return false;
//        return name.equals(person.name);
//
//    }

//    @Override
//    public int hashCode() {
////        System.out.println(super.hashCode());
////        return super.hashCode();
//        int result = id.hashCode();
//        result = 31 * result + name.hashCode();
//        return result;
//    }
}
